#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <iostream>
#include <fcntl.h>
#include <sys/epoll.h>
#include "common.h"
#include "msgport.h"
#include "MsgProcess.h"
#include "assert.h"
#include <pthread.h>
#include "DBServer.h"
#include "LoginManager.h"

#define SERVER_PORT 9999
#define MAX_CON 10

using namespace std;

MsgQueue msgQueue;

CMsgProcess msgProcess;

CDBServer* cdbserver;

int epfd;
struct epoll_event ev, events[200];

void* CheckMsgSize(void* args)
{
	while(1)
	{
		cout<<"Size of msg is "<<msgQueue.GetSize()<<endl;

		sleep(1);
	}

}


//设置socket非阻塞
bool setNoBlock(int fd)
{
	assert(fd);
	if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
	{
		perror("set noblock fail\n");
		return false;
	}
	return true;
}

//初始化Epoll
bool initEpoll(int serverSocket)
{

	epfd = epoll_create(1000);
	if (fcntl(serverSocket, F_SETFL, O_NONBLOCK) == -1) {
		perror("fcntl");
		return false;
	}

	ev.data.fd = serverSocket;
	ev.events = EPOLLIN|EPOLLET;

	if (epoll_ctl(epfd, EPOLL_CTL_ADD, serverSocket, &ev) == 0)
		return true;
	return false;
}



int main()
{
	socklen_t sin_size = 0;
	int sockfd,client_fd;
	sockaddr re_addr;
	struct sockaddr_in my_addr;
	struct sockaddr_in client_addr;
	cdbserver = new CDBServer();

	msgProcess.Init(&msgQueue);

	CLoginManager* loginManager = new CLoginManager(CDBServer::m_con);

	if((sockfd = socket(AF_INET, SOCK_STREAM,0)) == -1)
	{
		perror("Socket 创建失败");
		exit(1);
	}

	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(SERVER_PORT);
	my_addr.sin_addr.s_addr = INADDR_ANY;

	if (bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) == -1)
	{
		perror("bind 出错!");
		exit(1);
	}
	if (listen(sockfd,10)<0)       /*监听一个端口。*/
	{
		perror("listen");        /*错误则输出提示。*/
		exit(1);
	}

	if(initEpoll(sockfd))
		printf("set epoll success\n");
	else
		printf("set epoll error\n");


	sin_size = sizeof(struct sockaddr);

	msgProcess.Start();
	//pthread_t pid;
	//pthread_create(&pid,NULL,CheckMsgSize,NULL);

	while(1)
	{
		int nfds = epoll_wait( epfd,events, 50, 500);

		if(nfds == 0 )
			continue;

		for (int i = 0; i< nfds; i++)
		{
			if( events[i].data.fd == sockfd)
			{
				printf("get a new socket!");
				if ( client_fd = accept(sockfd, (struct sockaddr*)&re_addr,&sin_size))
				{
					if(setNoBlock(client_fd))
					{
						printf("set socket no block success!\n");
						ev.data.fd = client_fd;
						ev.events = EPOLLIN|EPOLLET;
						epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &ev);
						loginManager->AddNewUser(ev.data.fd);					
					}
					else
						perror("fail set block \n");
				}

			}
			else if(events[i].events & EPOLLIN)
			{
				int tempfd;

				if (tempfd = events[i].data.fd < 0)continue;

				char buf[1024];
				int msg_size = recv(events[i].data.fd,buf,1024,0);

				if ( msg_size <= 0 )
				{
					close(tempfd);
					ev.data.fd = tempfd;
					ev.events = EPOLLIN|EPOLLET;
					epoll_ctl(epfd, EPOLL_CTL_DEL,tempfd,&ev);

					events[i].data.fd = -1;
					printf("close socket");
				}
				else
				{
					MSG_HEAD* msgHead = (MSG_HEAD*)buf;

					msgQueue.PushMsg(msgHead, msgHead->MSG_SIZE);
					
					ev.data.fd=events[i].data.fd;
					ev.events=EPOLLIN|EPOLLOUT|EPOLLET;
					char name[12] = "singe";
					send(ev.data.fd, (void*)name,sizeof(name),MSG_DONTWAIT);
					epoll_ctl(epfd,EPOLL_CTL_MOD, tempfd,&ev);
					
				}

			}


		}

	}






	return 1;
}
